package org.finesys.common.netty.websocket.stomp.support;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.stomp.*;

import java.util.List;

/**
 * stomp 帧编码器，将STOMP子帧编码为WebSocket帧。
 */
public class StompWebSocketFrameEncoder extends StompSubframeEncoder {

    /**
     * 重写父类的encode方法，将STOMP子帧编码为WebSocket帧。
     *
     * @param ctx ChannelHandlerContext，表示ChannelHandler和它的Channel之间的绑定，ChannelHandlerContext提供了很多有用的操作
     * @param msg StompSubframe，需要编码的STOMP子帧
     * @param out List<Object>，用于存放编码后的WebSocket帧
     * @throws Exception 编码过程中可能会抛出异常
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, StompSubframe msg, List<Object> out) throws Exception {
        super.encode(ctx, msg, out);
    }

    /**
     * 将STOMP帧转换为WebSocket帧
     *
     * @param original 原始STOMP帧
     * @param encoded  编码后的ByteBuf
     * @return 根据原始STOMP帧的类型，返回对应的WebSocket帧（TextWebSocketFrame或BinaryWebSocketFrame）
     */
    @Override
    protected Object convertFullFrame(StompFrame original, ByteBuf encoded) {
        if (isTextFrame(original)) {
            return new TextWebSocketFrame(encoded);
        }
        return new BinaryWebSocketFrame(encoded);
    }

    /**
     * 将STOMP头部子帧转换为WebSocket帧
     *
     * @param original 原始STOMP头部子帧
     * @param encoded  编码后的ByteBuf
     * @return 根据原始STOMP头部子帧的类型，返回对应的WebSocket帧（TextWebSocketFrame或BinaryWebSocketFrame）
     * - 如果为文本帧，则返回TextWebSocketFrame
     * - 否则，返回BinaryWebSocketFrame
     */
    @Override
    protected Object convertHeadersSubFrame(StompHeadersSubframe original, ByteBuf encoded) {
        if (isTextFrame(original)) {
            return new TextWebSocketFrame(false, 0, encoded);
        }
        return new BinaryWebSocketFrame(false, 0, encoded);
    }

    /**
     * 将STOMP内容子帧转换为WebSocket帧
     *
     * @param original 原始STOMP内容子帧
     * @param encoded  编码后的ByteBuf
     * @return 根据原始STOMP内容子帧的类型，返回对应的WebSocket帧（ContinuationWebSocketFrame）
     * - 如果原始子帧是LastStompContentSubframe，则返回一个标记为结束的ContinuationWebSocketFrame
     * - 否则，返回一个未标记为结束的ContinuationWebSocketFrame
     */
    @Override
    protected Object convertContentSubFrame(StompContentSubframe original, ByteBuf encoded) {
        if (original instanceof LastStompContentSubframe) {
            return new ContinuationWebSocketFrame(true, 0, encoded);
        }
        return new ContinuationWebSocketFrame(false, 0, encoded);
    }

    /**
     * 判断给定的STOMP头部子帧是否为文本帧
     *
     * @param headersStompFrame STOMP头部子帧对象
     * @return 如果头部子帧的Content-Type为"text/plain"或"application/json"，则返回true，否则返回false
     */
    private static boolean isTextFrame(StompHeadersSubframe headersStompFrame) {
        String contentType = headersStompFrame.headers().getAsString(StompHeaders.CONTENT_TYPE);
        return contentType != null && (contentType.startsWith("text/plain") || contentType.startsWith("application/json"));
    }
}
